header{
/* codigo de cabecera */
}
options{
/* opciones comunes a toda la especificacion */
}

///////////////////////////////
// Analizador lexico
///////////////////////////////
class Analex extends Lexer;

// ... Zona de opciones
options {
	k=2;
	charVocabulary = '\3'..'\377';
	caseSensitiveLiterals=false;
}
tokens{
	LIT_REAL;
	LIT_ENTERO;
	INT = "int";
	VOID = "void";
	CHAR = "char";
	WHILE = "while";
	IF = "if";
	RETURN = "return";
}
{
	// http://antlr.org/share/1084743321127/ANTLR_Reference_Manual.pdf
	// Pagina 60
	public void tab() {
		int t = 4;
		int c = getColumn();
		int nc = (((c-1)/t)+1)*t+1;
		setColumn( nc );
	}
	
}

protected TAB: '\t';

protected NUEVA_LINEA: "\r\n" {newline();};

// Corregido para que cuente bien las lineas
COMENTARIO
  : 
  (	"/*"
    (
      options {
        generateAmbigWarnings=false;
      }
      :  { LA(2)!='/' }? '*'
      | '\r' '\n' {newline();}
      | '\r' {newline();}
      | '\n' {newline();}
      | ~('*'|'\n'|'\r')
    )*
    "*/"
 | "//" (~('\n'|'\r'))* 
 | "<!--" 
 	( options {
        generateAmbigWarnings=false;
      }
      : '\r' '\n' {newline();}
      | '\r' {newline();}
      | '\n' {newline();}
      | ~('-'|'\n'|'\r')
    )*
    "-->"
 )	{$setType(Token.SKIP);}
;

BLANCO: (' '|TAB|NUEVA_LINEA) {$setType(Token.SKIP);};
protected DIGITO: '0'..'9';
NUMERO : ((DIGITO)+ '.') => (DIGITO)+ '.' (DIGITO)*	{$setType(LIT_REAL);}
						| 	(DIGITO)+ {$setType(LIT_ENTERO);}
						;
protected LETRA: ('A'..'Z')|('a'..'z');
IDENT : (LETRA)((DIGITO)|(LETRA))*;

OPERADOR: '+'|'-'|'/'|'*';
PARENTESIS_ABIERTO: '(';
PARENTESIS_CERRADO: ')';
LLAVE_ABIERTA: '{';
LLAVE_CERRADA: '}';
COCH_ABIERTO: '[';
COCH_CERRADO: ']';
DEF_CHAR: COCH_ABIERTO ((LETRA|DIGITO) (OPERADOR (LETRA|DIGITO))?)+ COCH_CERRADO;

ABRIR: "%{";
CERRAR: "%}";
SEPARADOR: ';';

REGLA: "%%";
BARRA: '|';

COMA: ',';
ASIGNACION: "=";
CADENA: '"' (~('"'))* '"';
PORCENTAJE: '%';

AMPERSAN: '&';
IGUAL: "==";
MENOR_QUE : '<';
MAYOR_QUE : '>';
MAYOR_IGUAL: ">=";
MENOR_IGUAL: "<=";

PUNTO : '.';

///////////////////////////////
// Analizador sintactico
///////////////////////////////
class Anasint extends Parser;

options {
	k=1;
	defaultErrorHandler=false;
}

entrada : (unidades)* (declaraciones) (reglas) (codigo) EOF;
unidades : IDENT DEF_CHAR;

tipo: (CHAR|INT); 
declaraciones : ABRIR (tipo IDENT SEPARADOR)* CERRAR;
reglas : REGLA (regla)* REGLA;
regla:  operador (BARRA operador)*; 
operador: factor (OPERADOR)*;
factor: (PARENTESIS_ABIERTO regla PARENTESIS_CERRADO) | (LLAVE_ABIERTA IDENT LLAVE_CERRADA) | incremento;
incremento: IDENT (OPERADOR)* SEPARADOR;

codigo: (funcion)*;
funcion: tipo IDENT PARENTESIS_ABIERTO (def_parametros|VOID)? PARENTESIS_CERRADO LLAVE_ABIERTA (sentencia)* (salida)? LLAVE_CERRADA;
def_parametros: def_parametro (COMA def_parametro)*;
def_parametro: tipo (OPERADOR)? IDENT (COCH_ABIERTO COCH_CERRADO)?;
salida: RETURN LIT_ENTERO SEPARADOR;
sentencia: parametro (tipo_sentencia)? SEPARADOR;
tipo_sentencia: asignacion | llamada;
asignacion: ASIGNACION parametro (tipo_sentencia)?;
llamada: PARENTESIS_ABIERTO (parametros)? PARENTESIS_CERRADO;
parametros: parametro (COMA parametro)*;
parametro: IDENT (COCH_ABIERTO LIT_ENTERO COCH_CERRADO)? | LIT_ENTERO | LIT_REAL | CADENA;




